/**
* Copyright 2008 Sunnada Co.,Ltd
* All right reserved.
* 与中间服务通讯程序通讯,负责发送数据
* V1.0.0   WTJ    2008-11-14  Created
*/

package com.sunnada.edu.system.pub.socket;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

import org.apache.commons.io.IOUtils;
import com.sunnada.edu.system.pub.socket.Switch;
import com.sunnada.edu.system.pub.util.DateUtil;
import com.sunnada.edu.system.pub.xml.XmlParse;

public class SockData
{
  public SockData(){}

  //定义静态SOCK
  //定义静态SOCK
   public static Socket FSocket[]=null;
   public static String FHost[]=null;
   public static int    FPort[]=null;
   public static OutputStream FOutputStream[]=null;

   private static final String SOCK_CONFIG_FILE="appini.xml";
   private static String sConfigFileName=null;
   private static String sContent=null;
   public static boolean bRead=false;
   private static boolean bLock=false;
   //心跳
   public static int FHeartMinute=3600;
   public static int FHeartDbNum=6;
   //数据处理线程
   public static int FDealThreadNum=5;

   public synchronized static boolean readConfigFile()
   {
     try
     {
       if(sContent==null)
       {
         if(Switch.TcpDebug) System.err.println("Begin Read SOCK INI Data.");
         SockData dbcfg=new SockData();
         ClassLoader cl=dbcfg.getClass().getClassLoader();

         InputStream input=cl.getResourceAsStream(SOCK_CONFIG_FILE);
         sConfigFileName=cl.getResource(SOCK_CONFIG_FILE).toString();
         cl=null;

         int iNum=input.available();
         byte[] aContent=new byte[iNum];
         input.read(aContent);
         input.close();
         sContent=new String(aContent);
       }
       if(Switch.TcpDebug) System.err.println("Read Config XML File:["+sConfigFileName+"]");
       bRead=true;
       return true;
     }
     catch (Exception ex)
     {
       System.out.println("readConfigFile()==>"+ex.toString());
       sContent=null;
       bRead=false;
       return false;
     }
   }
   public synchronized static boolean readini()
   {
     try
     {
       if(Switch.TcpDebug) System.err.println("Begin Read INI data.");
       XmlParse xml=new XmlParse();
       if(!xml.bGetXML(sContent))
       {
         System.out.println(xml.ErrMsg);
         return false;
       }
       //1.得到SOCKET连接池的个数
       int iNum=xml.GetNameNum("sock");
       //设置数组
       FSocket=new Socket[iNum];
       FHost  =new String[iNum];
       FPort  =new int[iNum];
       FOutputStream=new OutputStream[iNum];

       for(int i=0;i<iNum;i++)
       {
         try
         {
           FHost[i]=xml.sGetValueByName("host",i);
           FPort[i]=Integer.parseInt(xml.sGetValueByName("port", i));
         }
         catch(Exception ex2)
         {
           System.out.println("ReadIni==>"+ex2.toString());
           return false;
         }
         //只读第一个
         //break;
       }
       //2.得到心跳配置数据
       iNum=xml.GetNameNum("heart");
       for(int i=0;i<iNum;i++)
       {
         try
         {
           FHeartMinute=Integer.parseInt(xml.sGetValueByName("HeartMinute",i));
           FHeartDbNum =Integer.parseInt(xml.sGetValueByName("HeartDbNum", i));
         }
         catch(Exception ex2)
         {
           System.out.println("ReadIni==>"+ex2.toString());
           return false;
         }
         //只读第一个
         break;
       }
       //3.数据处理线程
       iNum=xml.GetNameNum("DealData");
       for(int i=0;i<iNum;i++)
       {
         try
         {
           FDealThreadNum=Integer.parseInt(xml.sGetValueByName("ThreadNum",i));
         }
         catch(Exception ex2)
         {
           System.out.println("ReadIni==>"+ex2.toString());
           return false;
         }
         //只读第一个
         break;
       }

       if(Switch.TcpDebug) System.err.println("End Read INI data.");
       return true;
     }
     catch (Exception ex)
     {
       System.out.println("ReadIni()==>"+ex.toString());
       return false;
     }
   }

   public static void freeClassEvent()
   {
     try
     {
       for (int i=0;i<FSocket.length;i++)
         FSocket[i].close();
       System.out.println("Socket is Closed");
     }
     catch (Exception ex)
     {
       System.out.println("Socket is Closed:"+ex.toString());
     }
   }

   public static boolean isLock()
   {
     return bLock;
   }

   public static void lock()
   {
     bLock=true;
   }

   public static void unlock()
   {
     bLock=false;
   }
   public synchronized static String SendData(String pCmd,String pData)
   {
     String lReturn="";
     if(!bRead)
     {
       readConfigFile();
       readini();
     }

     for (int i=0;i<FSocket.length;i++)
       lReturn=SendData(pCmd,pData,i);
     return lReturn;
   }
   //发送数据 pCmd = 1001,1002等数据,如果数据很长,则要分多次发送,一般长度控制在1024以内
   public synchronized static String SendData(String pCmd,String pData,int pIndex)
   {
     String lReturn="";
     try
     {
       //判断SOCK是否为关闭的
       if (FSocket[pIndex]==null || FSocket[pIndex].isClosed())
       {
         //判断是否已经读配置文件
         if(!bRead)
         {
           readConfigFile();
           readini();
         }
         if(Switch.TcpDebug) System.err.println(DateUtil.getNowTime()+" 索引["+pIndex+"]连接Socket.");
         FSocket[pIndex]=null;
         FSocket[pIndex]= new Socket(FHost[pIndex],FPort[pIndex]);
         if (FOutputStream[pIndex]!=null)
         FOutputStream[pIndex].close();
         FOutputStream[pIndex]=FSocket[pIndex].getOutputStream();
       }
       //判断是否Active
       try
       {
         FSocket[pIndex].sendUrgentData(0xFF);
       }catch(Exception ex)
       {
         if(Switch.TcpDebug) System.err.println("判断活动:"+ex.toString());
         if (!FSocket[pIndex].isClosed())
         FSocket[pIndex].close();
         FSocket[pIndex]=null;
         FSocket[pIndex]=new Socket(FHost[pIndex],FPort[pIndex]);
         FOutputStream[pIndex]=FSocket[pIndex].getOutputStream();
         if(Switch.TcpDebug) System.err.println(DateUtil.getNowTime()+" 索引["+pIndex+"]重新连接Socket.");
       }
       //发送数据
       //长度(2)+命令(2)+内容(变长)+校验(2)
       String lData=pCmd+pData;
       lData=FunCmd.WordToFourAscii(lData.getBytes("GBK").length+8) + lData+FunCmd.totalAscSum(lData);
       FOutputStream[pIndex].write(lData.getBytes("GBK"));
       FOutputStream[pIndex].flush();
       if(Switch.TcpDebug) System.err.println(DateUtil.getNowTime()+" 索引["+pIndex+"]发送数据 "+lData);
     }
     catch (Exception ex)
     {
       FSocket[pIndex]=null;
       lReturn="SendData():"+ex.toString();
       if(Switch.TcpDebug) System.err.println(DateUtil.getNowTime()+" 索引["+pIndex+"]= "+lReturn);
     }finally{
		try {
			 if(FSocket[pIndex]!=null)
				 FSocket[pIndex].close();
			 if(FOutputStream[pIndex]!=null)
	    		 FOutputStream[pIndex].close();
		} catch (IOException e) {
			e.printStackTrace();
		}
     }
     return lReturn;
   }
   public synchronized static String SendData_utf8(String pCmd,String pData)
   {
     String lReturn="";
     if(!bRead)
     {
       readConfigFile();
       readini();
     }

     for (int i=0;i<FSocket.length;i++)
       lReturn=SendData_utf8(pCmd,pData,i);
     return lReturn;
   }
   //发送数据 pCmd = 1001,1002等数据,如果数据很长,则要分多次发送,一般长度控制在1024以内
   public synchronized static String SendData_utf8(String pCmd,String pData,int pIndex)
   {
     String lReturn="";
     try
     {
       //判断SOCK是否为关闭的
       if (FSocket[pIndex]==null || FSocket[pIndex].isClosed())
       {
         //判断是否已经读配置文件
         if(!bRead)
         {
           readConfigFile();
           readini();
         }
         if(Switch.TcpDebug) System.err.println(DateUtil.getNowTime()+" 索引["+pIndex+"]连接Socket.");
         FSocket[pIndex]=null;
         FSocket[pIndex]= new Socket(FHost[pIndex],FPort[pIndex]);
         if (FOutputStream[pIndex]!=null)
         FOutputStream[pIndex].close();
         FOutputStream[pIndex]=FSocket[pIndex].getOutputStream();
       }
       //判断是否Active
       try
       {
         FSocket[pIndex].sendUrgentData(0xFF);
       }catch(Exception ex)
       {
         if(Switch.TcpDebug) System.err.println("判断活动:"+ex.toString());
         if (!FSocket[pIndex].isClosed())
         FSocket[pIndex].close();
         FSocket[pIndex]=null;
         FSocket[pIndex]=new Socket(FHost[pIndex],FPort[pIndex]);
         FOutputStream[pIndex]=FSocket[pIndex].getOutputStream();
         if(Switch.TcpDebug) System.err.println(DateUtil.getNowTime()+" 索引["+pIndex+"]重新连接Socket.");
       }
       //发送数据
       //长度(2)+命令(2)+内容(变长)+校验(2)
       byte[]byteUtf_8 = IOUtils.toByteArray(IOUtils.toInputStream(pCmd+pData, "UTF-8"));
       String lData=FunCmd.WordToFourAscii(byteUtf_8.length+8);
       FOutputStream[pIndex].write(lData.getBytes());
       FOutputStream[pIndex].write(byteUtf_8);
       lData = FunCmd.totalAscSum(byteUtf_8);
       FOutputStream[pIndex].write(lData.getBytes());
       FOutputStream[pIndex].flush();
       if(Switch.TcpDebug) System.err.println(DateUtil.getNowTime()+" 索引["+pIndex+"]发送数据 "+pData);
     }
     catch (Exception ex)
     {
       FSocket[pIndex]=null;
       lReturn="SendData():"+ex.toString();
       if(Switch.TcpDebug) System.err.println(DateUtil.getNowTime()+" 索引["+pIndex+"]= "+lReturn);
     }finally{
		try {
			 if(FSocket[pIndex]!=null)
				 FSocket[pIndex].close();
			 if(FOutputStream[pIndex]!=null)
	    		 FOutputStream[pIndex].close();
		} catch (IOException e) {
			e.printStackTrace();
		}
     }
     return lReturn;
   }
  //关闭TCP
  public static void DelTask(String pHint) {
    String status = pHint+"清理TCP连接！";
    System.out.println(status);
    for (int i=0;i<SockData.FSocket.length;i++)
    {
      try{
        if ((SockData.FSocket[i] != null) && !SockData.FSocket[i].isClosed())
        {
          SockData.FSocket[i].close();
          System.out.println("索引["+i+"]Java重新加载,SOCKET关闭.");
        }
      }catch (Exception e)
      {
        e.printStackTrace();
      }
    }
  }

  public static void main(String[] args) throws Exception {
    //SockData tcp = new SockData();
    //tcp.receiver(20000);
    //tcp.send("127.0.0.1",2020);
    //for (int i=0;i<5;i++)

    //测试数据
    SockData.SendData("1000","不");

    //测试读数据
    //ReadSockData tcp = new ReadSockData();
    //tcp.CreateThread();
    //Thread.currentThread().sleep( (int) (1000*1000));

    //测试十六进制数
    //System.err.print(FunCmd.toStringHex("3130350F20"));

  }

}


